#include "tcp_iperf.h"
#include "lwip/apps/lwiperf.h"
#include "arpa/inet.h"
#include "cmd_input.h"


#define CMD_DESC_INFO_LEN 32

typedef void(*CmdFunc)(void);
typedef struct {
    char desc[CMD_DESC_INFO_LEN];
    CmdFunc func;
} CmdNode;
static volatile bool bExit = false;
static void Exit(void);
static void StartTcpIperfServer(void);
static void StartTcpIperfClient(void);

static CmdNode g_cmdList[] = {
    { "NULL", NULL},
    { "StartTcpIperfServer", StartTcpIperfServer },
    { "StartTcpIperfClient", StartTcpIperfClient },
    { "Exit", Exit }, /* keep Exit at last */
};
static unsigned int g_cmdNum = sizeof(g_cmdList) / sizeof(CmdNode);

static void Exit(void)
{
    bExit = true;
}

static void Helper(void)
{
    printf("******TCP iperf test tools command list******\r\n");
    for (unsigned int i = 0; i < g_cmdNum; i++) {
        printf("*     %02d - %-20s     *\r\n", i, g_cmdList[i].desc);
    }
    printf("*************************************\r\n");
}

static bool enterReportFnFlag = false;
static bool WaitForEnterReportFnFlag(void)
{
    while(enterReportFnFlag == false)
    {
        osDelay(100);
    }
    enterReportFnFlag = false;
}

static void EnterReportFnFlag(void)
{
    enterReportFnFlag = true;
}

void TcpIperfReportFn(void *arg, enum lwiperf_report_type report_type,
                      const ip_addr_t* local_addr, u16_t local_port, const ip_addr_t* remote_addr, u16_t remote_port,
                      u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec)
{   
    printf("****** Report report_type:%d ******\r\n", report_type);
    printf("****** Report local_addr:%s, local_port:%d ******\r\n", inet_ntoa(local_addr->u_addr.ip4), local_port);
    printf("****** Report remote_addr:%s, remote_port:%d ******\r\n", inet_ntoa(remote_addr->u_addr.ip4), remote_port);
    printf("****** Report bytes_transferred:%d Bytes, ms_duration:%d, bandwidth_kbitpsec:%d Kbits/sec ******\r\n", 
                                                      bytes_transferred, ms_duration, bandwidth_kbitpsec);
    EnterReportFnFlag();
}

static void StartTcpIperfServer(void)
{
    lwiperf_start_tcp_server_default(TcpIperfReportFn, NULL);
    while(1)
    {
        osDelay(1000);
    }
}

static void StartTcpIperfClient(void)
{
    ip_addr_t remote_addr;
    char ipBuf[20] = {0};

    GetInputString("Please input ip of remote server:", ipBuf, 20);
    remote_addr.type = IPADDR_TYPE_V4;
    inet_aton(ipBuf, &remote_addr.u_addr.ip4);
    lwiperf_start_tcp_client_default(&remote_addr, TcpIperfReportFn, NULL);
    WaitForEnterReportFnFlag();
}

void AppStartIperfTools(void)
{
    int32_t index;
    char char_buf;

    osDelay(2500);
    printf("******AppStartIperfTools start******\r\n");
    do {
        Helper();
        index = GetInputNumber("Please input cmd index:");
        if (bExit) 
            break;
        if (index < 0 || index >= g_cmdNum) {
            printf("invalid cmd: %d\r\n", index);
            continue;
        }
        if(index != 0)
        {
            printf("\r\ncmd: %d\r\n", index);
            printf("\r\nExecute: %s\r\n", g_cmdList[index].desc);
            g_cmdList[index].func();
        }else{
            printf("\r\ncmd invalid\r\n", index);
        }
        osDelay(200U);
    } while ((index + 1) != g_cmdNum && bExit == false);
    printf("******AppStartIperfTools exit******\r\n");
}


